--[[
	Title: ConCommand Helpers
	
	Server-side compliment of the shared concommand.lua
]]

--[[
	Table: sayCmds
	
	This table holds our say commands.
]]
ULib.sayCmds = {}

-- This function is used to send autocompletes to players.
local function autocomplete( ply )
	for command, info in pairs( ULib.autocompletes ) do
		umsg.Start( "ULib_autocomplete", ply )
			umsg.String( command )
			umsg.String( info.cl )
		umsg.End()
	end
end
hook.Add( "ULibPlayerULibLoaded", "ULibSendAutocomplete", autocomplete )

-- We'll be receiving commands from the client here in hex (to avoid garry blocks)
local function redirectedCommand( ply, command, argv )
	local args = argv[ 1 ]

	local realArgs = ""
	if args then
		while args:len() > 1 do
			local byte = args:sub( 1, 2 ) -- Grab the next hex value
			args = args:sub( 3 ) -- Chop it out of the original string
			realArgs = realArgs .. string.char( tonumber( byte, 16 ) ) -- Convert!
		end
	end

	argv = ULib.splitArgs( realArgs )
	command = argv[ 1 ]
	table.remove( argv, 1 )
	ULib.autocompletes[ command ].sv( ply, "_" .. command, argv )
end
concommand.Add( "_ulib_command", redirectedCommand )

--[[
	Function: convar

	Adds a cvar which clients (with permission) can access and change.

	Parameters:

		cvar_name - The cvar name. IE, "ulx_hostname2".
		value - The value to start off at.
		cmd_help - *(Optional)* The help for the command.
		cmd_access - *(Optional, defaults to ULib.ACCESS_ALL)* The access for the command.
]]
function ULib.convar( cvar_name, value, cmd_help, cmd_access )
	CreateConVar( cvar_name, value )
	local f = function ( ply, command, argv, args ) -- This function will handle the cvar ( command ) callback
		args = ULib.stripQuotes( args )
		if args == "" then
			ULib.console( ply, "\"" .. cvar_name .. "\" = \"" .. GetConVarString( cvar_name ) .. "\"" )
			if cmd_help then
				ULib.console( ply, cmd_help .. "\n  CVAR generated by ULib" )
			else
				ULib.console( ply, "  CVAR generated by ULib" )
			end
		else
			ULib.consoleCommand( cvar_name .. " " .. string.format( "%q", args ) .. "\n" )
		end
	end
	return ULib.concommand( cvar_name, f, _, cmd_help, cmd_access )
end


--[[
	Function: add_subconvar

	Adds a sub cvar which clients (with permission) can access and change. See <add_subconcommand()>.

	Parameters:

		prefix - The prefix to use, IE: "ulx"
		cvar_name - The cvar name. IE, "hostname2".
		value - The value to start off at.
		cmd_help - *(Optional)* The help for the command.
		cmd_access - *(Optional, defaults to ACCESS_ALL)* The access for the command.
]]
function ULib.add_subconvar( prefix, cvar_name, value, cmd_help, cmd_access )
	local cvar_name2 = string.gsub( prefix, " ", "_" ) .. "_" .. cvar_name
	CreateConVar( cvar_name2, value )	
	local f = function ( ply, command, argv, args ) -- This function will handle the cvar ( command ) callback
		args = ULib.stripQuotes( args )
		if args == "" then
			ULib.console( ply, "\"" .. cvar_name .. "\" = \"" .. GetConVarString( cvar_name2 ) .. "\"" )
			if cmd_help then
				ULib.console( ply, cmd_help .. "\n  CVAR generated by ULib" )
				return
			else
				ULib.console( ply, "  CVAR generated by ULib" )
				return
			end
		else
			ULib.consoleCommand( cvar_name2 .. " " .. string.format( "%q", args ) .. "\n" )
		end
	end

	return ULib.add_subconcommand( prefix, cvar_name, f, cmd_help, cmd_access )
end


--[[
	Function: sayCmdCheck
	
	Say callback which will check to see if there's a say command being used. *DO NOT CALL DIRECTLY*

	Parameters:
		
		ply - The player.
		strText - The text.
		bPublic - Public say.
		
	Revisions:
	
		v2.10 - Made case-insensitive
]]
local function sayCmdCheck( ply, strText, bPublic )
	local match
	for str, data in pairs( ULib.sayCmds ) do
		local str2 = str
		if strText:len() < str:len() then -- Go ahead and allow commands w/o spaces
			str2 = string.Trim( str )
		end
		
		if strText:sub( 1, str2:len() ):lower() == str2 then
			if not match or match:len() <= str:len() then -- Don't rematch if there's a more specific one already.
				match = str
			end
		end
	end

	if match then -- We've got a winner!
		local data = ULib.sayCmds[ match ]
		if not ULib.ucl.query( ply, data.access ) then
			ULib.tsay( ply, "You do not have access to this command, " .. ply:Nick() .. "." )
			-- Print their name to intimidate them :)
			return "" -- Block from appearing
		end

		local args = string.Trim( strText:sub( match:len() + 1 ) ) -- Strip the caller command out
		local argv = ULib.splitArgs( args )
		local fn = data.fn
		local hide = data.hide

		PCallError( fn, ply, match, argv, args )
		if hide then return "" end
	end

	return nil
end
hook.Add( "PlayerSay", "ULib_saycmd", sayCmdCheck, 10 ) -- Low-priority


--[[
	Function: addSayCommand
	
	Just like ULib's <concommand()> except that the callback is called when the command is said in chat instead of typed in the console.

	Parameters:
		
		say_cmd - A command string for says. IE: "!kick", then when someone says "!kick", it'll call the callback.
		fn_call - The function to call when the command's called.
		access - The access string to associate access with this say command. (IE: "ulx kick"). Remember to call <ULib.ucl.registerAccess()> if the access string isn't being used in a command.
		cmd_help - *(Optional)* A help string for using the command.
		hide_say - *(Optional, defaults to false)* If true, will hide the chat message. Use this if you don't want other people to see the command.
		nospace - *(Optional, defaults to false)* If true, a space won't be required after the command "IE: !slapbob" vs "!slap bob".
		
	Revisions:
		
		v2.10 - Added nospace parameter, made case insensitive
]]
function ULib.addSayCommand( say_cmd, fn_call, access, cmd_help, hide_say, nospace )
	say_cmd = string.Trim( say_cmd:lower() )
	
	if not nospace then
		say_cmd = say_cmd .. " "
	end
	
	if not access then
		ULib.error( "Invalid access passed to addSayCommand!" )
		return
	end
	ULib.sayCmds[ say_cmd ] = { fn=fn_call, hide=hide_say, cmd_help=cmd_help, access=access }
end


--[[
	Function: removeSayCommand
	
	Removes a say command.

	Parameters:
		
		say_cmd - The command string for says to remove.
]]
function ULib.removeSayCommand( say_cmd )
	ULib.sayCmds[ say_cmd ] = nil -- Remove both forms
	ULib.sayCmds[ say_cmd .. " " ] = nil	
end